[LINUX] Do not early-unpin pagetables that contain foreign mappings.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 1 Aug 2006 14:48:48 +0000 (15:48 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 1 Aug 2006 14:48:48 +0000 (15:48 +0100)
This fixes a bug whereby foreign pages were freed by the unpin, which
then become owned by the local domain before it destroys its ptes.
It therefore (erroneously) detects the mappings as local and so
updates reference counts, leading to crashes.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/arch/i386/kernel/ldt-xen.c
linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu.h
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/mmu.h

index 06970d951759692de2cd7ea7c3a1f99f532aea0b..d2cceffbb1c379c8513b9b8bdecc7334bea3cd58 100644 (file)
@@ -109,6 +109,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
        init_MUTEX(&mm->context.sem);
        mm->context.size = 0;
+       mm->context.has_foreign_mappings = 0;
        old_mm = current->mm;
        if (old_mm && old_mm->context.size > 0) {
                down(&old_mm->context.sem);
index 1de992b2285bdaa9cc9778ffe8801adf0ceacad6..343826970552b52c68c32be85fd1477b8d072b94 100644 (file)
@@ -126,6 +126,8 @@ int direct_remap_pfn_range(struct vm_area_struct *vma,
        if (domid == DOMID_SELF)
                return -EINVAL;
 
+       vma->vm_mm->context.has_foreign_mappings = 1;
+
        return __direct_remap_pfn_range(
                vma->vm_mm, address, mfn, size, prot, domid);
 }
index a551252c7167f246752b91f10643510a4df74b3f..843c9d0fd3a461b66e0f1d78b03a0703ebd3b1c5 100644 (file)
@@ -694,6 +694,7 @@ void _arch_exit_mmap(struct mm_struct *mm)
        task_unlock(tsk);
 
        if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
-           (atomic_read(&mm->mm_count) == 1))
+           (atomic_read(&mm->mm_count) == 1) &&
+           !mm->context.has_foreign_mappings)
                mm_unpin(mm);
 }
index 721c47b1fd0a5e8168d79e0cdeadb691417ff98d..3641bfb805ebaf955417010c5696c2084c9b7818 100644 (file)
@@ -159,7 +159,8 @@ void _arch_exit_mmap(struct mm_struct *mm)
 
     task_unlock(tsk);
 
-    if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) )
+    if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+         !mm->context.has_foreign_mappings )
         mm_unpin(mm);
 }
 
index cba1785e392db1deb077734eaa8b50c089c6c47d..139e54a9be2107306f4d15ac7823e365014dcbff 100644 (file)
@@ -12,6 +12,9 @@ typedef struct {
        int size;
        struct semaphore sem;
        void *ldt;
+#ifdef CONFIG_XEN
+       int has_foreign_mappings;
+#endif
 } mm_context_t;
 
 /* mm/memory.c:exit_mmap hook */
index f95e8d5d79bfc3058b00944a88d116272905663e..2ac82529546021030476180b0a49c1fd8a135fb3 100644 (file)
@@ -17,6 +17,7 @@ typedef struct {
        struct semaphore sem; 
 #ifdef CONFIG_XEN
        unsigned pinned:1;
+       unsigned has_foreign_mappings:1;
        struct list_head unpinned;
 #endif
 } mm_context_t;